我們已經完成 CRUD 中的 CUD 了,現在就只差臨門一腳。
今日要來講講如何使用 JS 取得 Firebase DB
中的資料!
主要使用兩個方法:
on
once
第一個 on
會即時更新,也就是只要資料庫一變動,就會抓取到最新資料。
第二個 once
顧名思義只會取得一次,也就是執行時會從資料庫取得最新資料,但往後的更新將不會連動到 client 端的資料,除非再執行一次。
兩者有沒優劣之分,純粹是使用情境不同,像是留言板就能夠使用 on
來讓畫面即時顯示最新的留言。而比較不常變動且數量較多的資料,則可使用 once
。
雖然
on
很方便,但免費額度的限制下,同時間只允許 100 個連線源。
那就先來介紹 once
吧。
我們一樣舉昨天 Bob 國文成績的例子
題外話,我的國文成績一直都不是很好,上課老師開始講課文就睡著Q_Q
如果我們想要取得 Bob 的所有成績,就可以這樣寫:
db.ref("chinese/Bob").once('value', function (snapshot) {
var data = snapshot.val();
console.log(data);
});
=> 路徑為 chinese/Bob
,
=> 然後使用 once
取得最新的資料,
=> 再來是 callback function 中,會有一個參數用來接收從資料庫取出的值,大多習慣會命名為 snapshot
,
=> 要取得裡面的值可以使用 val()
方法。
所以印出來會長這樣:
都會了嗎,那這邊出個例題,如果我只想要單純取得 Bob 第三次的成績呢?
想好了嗎?
答案是
Ans:
db.ref("chinese/Bob/grade3").once('value', function (snapshot) {
var data = snapshot.val();
console.log(data);
});
只需要再指定往下一層路徑就好~
因為這是非同步事件,所以想要對取得的資料進行後續操作時,記得寫在 callback function 中。
像是這樣:
db.ref("chinese/Bob").once('value', function (snapshot) {
renderUI(snapshot.val());
});
不然你會發現怎麼畫面都渲染不出來XD
不了解的可以回去看看 Day5
講完 once
的用法後,接下來講講這個即時更新資料的方法吧。
on
的用法和 once
幾乎一樣,把 once
改成 on
而已。
db.ref("chinese/Bob").on('value', function (snapshot) {
console.log(snapshot.val());
});
它的運作流程是:
不用擔心 on
的即時更新,會導致 callback function 不斷執行。
所以範例中首次取得資料後,只要資料庫沒有資料更動,就不會一直印出 Bob 的所有成績。
上面舉了留言板作為 on
的使用情境,那這邊就使用 on
來實現
「線上多人即時更新的 ToDoList」吧!
此範例使用六角學院前陣子舉辦的 The F2E - 前端修練精神時光屋 的 Week1 設計稿。
PS. 只有設計稿而已,還是要自己切版、寫 JS
接下來不會說明該專案的其他技術細節,只會著重在 Firebase on
的使用方法。
都玩過了嗎,也可以多開瀏覽器或使用手機來看看即時更新的效果~
有兩點需要注意:
接下來要看的重點其實也只有這個XD
這個專案透過 on
來取得最新的資料,然後把資料存起來後再執行過濾與渲染的動作。
講完了如何取得資料後,已經可以應用於大多數狀況,但還是有一些方法來解決特定的情境。
有學過 SQL
指令的都知道,我除了單純的 select
以外,還可以使用 order by
、limit
...等指令。
在 Firebase DB
中也有這些方法喔,我們就來看看如何使用吧。
Let's go!
我們在撈出資料時,其實可以多加 orderBy
這個方法來對取出的資料做排序。
常見的有這 3 種:
orderByChild()
: 針對特定子節點做排序,參數帶入想要排序的欄位就好。orderByKey()
: 不用帶入參數,依據資料的 key
來做排序。orderByValue()
: 不用帶入參數,依據路徑下的值來做排序。一樣舉回 Bob 的例子,目前資料庫長這樣:
假設我們想要取出他的成績,並且按照成績由低到高排序,那麼就可以這樣寫:
db.ref("chinese/Bob").orderByValue().once('value', function (snapshot) {
snapshot.forEach(function (item) {
console.log(item.key + " " + item.val());
})
});
PS. orderBy
撈到的資料記得用 forEach
取出
此時取出的資料就不是 90
> 50
> 70
,而是會變這樣:
假設今天狀況比較複雜一點,總共有 3 個人的成績:
若是我想針對每個人的成績做排序,將成績由低到高印出。
那麼可以使用 orderByChild
這樣寫:
db.ref("chinese").orderByChild("grade").once('value', function (snapshot) {
snapshot.forEach(function (item) {
console.log(item.key + " " + item.val().grade);
})
});
此時取出的資料也就由小到大了
講完了排序以後,當然不只這樣,接下來還要介紹兩種方法
PS. 限制的方法記得接在 orderBy
後面
第一個區間限制,我可以使用這 3 種方法指定取出的資料範圍:
startAt
endAt
equalTo
按照字面翻譯,startAt
是大於等於的意思、endAt
是小於等於的意思、equalTo
是等於的意思。
所以當我只想取出「有及格」的成績時,
可以這樣寫:
db.ref("chinese").orderByChild("grade").startAt(60).endAt(100).once('value', function (snapshot) {
snapshot.forEach(function (item) {
console.log(item.key + " " + item.val().grade);
})
});
透過 startAt(60).endAt(100)
過濾,所以就只印出 Alice
、May
的成績了。
至於 equalTo
的用法也是一樣,就不再寫範例。
講完了區間限制,還剩下最後一個筆數限制。
limitToFirst()
limitToLast()
這方法能夠限制取出的資料筆數,又細分為從頭開始的前幾筆和最尾端的幾筆。
假設我想要取出排序後的第一筆而已,也就是「成績最低的同學」。
那麼就可以這樣寫:
db.ref("chinese").orderByChild("grade").limitToFirst(1).once('value', function (snapshot) {
snapshot.forEach(function (item) {
console.log(item.key + " " + item.val().grade);
})
});
透過 limitToFirst(1)
取得排序後的第一筆資料,也就是最低分的 Bob。
反過來說,當我想取出「最高分的同學」時,就可以使用 limitToLast
:
db.ref("chinese").orderByChild("grade").limitToLast(1).once('value', function (snapshot) {
snapshot.forEach(function (item) {
console.log(item.key + " " + item.val().grade);
})
});
CRUD 的操作都已經完成,趕快學起來加快自己的開發速度,或是可以寫些小作品分享給別人囉!
下一篇會來介紹權限的部分
我們明天見